package com.heima.comment.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.heima.comment.service.CommentHotService;
import com.heima.comment.service.CommentService;
import com.heima.feigns.UserFeign;
import com.heima.model.behavior.pojos.ApCollection;
import com.heima.model.comment.dtos.CommentDTO;
import com.heima.model.comment.dtos.CommentLikeDTO;
import com.heima.model.comment.dtos.CommentSaveDTO;
import com.heima.model.comment.pojos.ApComment;
import com.heima.model.comment.pojos.ApCommentLike;
import com.heima.model.comment.vos.ApCommentVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.threadlocal.AppThreadLocalUtils;
import com.heima.model.user.pojos.ApUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CommentServiceImpl implements CommentService {
    @Autowired
    UserFeign userFeign;
    @Autowired
    MongoTemplate mongoTemplate;

    /**
     * 评论功能实现
     * @param dto
     * @return
     */
    @Override
    public ResponseResult saveComment(CommentSaveDTO dto) {
        //参数校验
        //判断用户是否登录
        ApUser apUser = AppThreadLocalUtils.getUser();
        if (apUser==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //文字过滤
        //保存评论
        ResponseResult<ApUser> result = userFeign.findUserById(apUser.getId());
        if(result.getCode()!=0 || result.getData() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE, "当前登录信息有误");
        }
        apUser = result.getData();
        ApComment apComment = new ApComment();
        apComment.setAuthorId(apUser.getId());
        apComment.setAuthorName(apUser.getName());
        apComment.setImage(apUser.getImage());
        apComment.setContent(dto.getContent());
        apComment.setArticleId(dto.getArticleId());
        apComment.setCreatedTime(new Date());
        apComment.setUpdatedTime(new Date());
        apComment.setLikes(0);
        apComment.setReply(0);
        apComment.setType((short) 0);
        apComment.setFlag((short) 0);
        mongoTemplate.save(apComment);
        return ResponseResult.okResult();
    }

    @Autowired
    CommentHotService commentHotService;
    /**
     * 评论点赞功能
     * @param dto
     * @return
     */
    @Override
    public ResponseResult like(CommentLikeDTO dto) {
        //判断用户是否登录
        ApUser apUser = AppThreadLocalUtils.getUser();
        if (apUser==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //查询评论
        ApComment apComment = mongoTemplate.findById(dto.getCommentId(), ApComment.class);
        if (apComment==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //判断是否重复点赞
        Query query = Query.query(Criteria.where("commentId").is(dto.getCommentId())
                .and("authorId").is(apUser.getId()));
        ApCommentLike apCommentLike = mongoTemplate.findOne(query, ApCommentLike.class);
        if (apCommentLike != null && dto.getOperation().intValue() == 0) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_EXIST, "已点赞");
        }
        //保存点赞数据
        if (dto.getOperation()==0){
            // 点赞+1
            apComment.setLikes(apComment.getLikes() + 1);
            mongoTemplate.save(apComment);
            //计算热点评论评论
            if (apComment.getLikes() >= 10 && apComment.getFlag().shortValue() == 0) {
                commentHotService.hotCommentExecutor(apComment);
            }
            //保存评论点赞信息
            apCommentLike = new ApCommentLike();
            apCommentLike.setAuthorId(apUser.getId());
            apCommentLike.setCommentId(apComment.getId());
            apCommentLike.setOperation(dto.getOperation());
            mongoTemplate.save(apCommentLike);
        }else {
            //取消点赞
            //减去点赞数,先判断是否小于或等于0,不是减一,是直接为0
            apComment.setLikes(apComment.getLikes() <= 0 ? 0: apComment.getLikes() - 1);
            mongoTemplate.save(apComment);
            //删除评论点赞信息
            mongoTemplate.remove(query,ApCommentLike.class);
        }
        //数据返回
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("likes",apComment.getLikes());
        return ResponseResult.okResult(resultMap);
    }

    /**
     * 查询评论列表
     * @param dto
     * @return
     */
    @Override
    public ResponseResult findByArticleId(CommentDTO dto) {
        //参数检查
        Integer size = dto.getSize();
        if ( size == null || size <= 0) {
            dto.setSize(10);
        }
        //查询文章所有评论列表
        /*Query query = Query.query(Criteria.where("articleId").is(dto.getArticleId())
                .and("createdTime").lt(dto.getMinDate()))
                .limit(dto.getSize())
                .with(Sort.by(Sort.Direction.DESC,"createdTime"));*/
        List<ApComment> apCommentList = null;

        if(dto.getIndex().intValue() == 1){ // 文章评论的首页
            //查询热点评论  5
            Query query = Query.query(Criteria.where("articleId").is(dto.getArticleId())
                    .and("flag").is(1))
                    .with(Sort.by(Sort.Direction.DESC, "likes"));
            apCommentList = mongoTemplate.find(query, ApComment.class);
            // 热点集合不为空
            if (CollectionUtils.isNotEmpty(apCommentList)) {
                size = dto.getSize() - apCommentList.size();
                List<ApComment> normalComments = mongoTemplate.find(getQuery(dto), ApComment.class);
                apCommentList.addAll(normalComments);
            }else {
                apCommentList = mongoTemplate.find(
                        getQuery(dto),
                        ApComment.class
                );
            }
        }else {
            //查询更多普通评论
            apCommentList = mongoTemplate.find(
                    getQuery(dto),
                    ApComment.class
            );
        }

        //判断用户是否登录
        ApUser user = AppThreadLocalUtils.getUser();
        if (user==null){
            //用户未登录直接返回评论列表
            return ResponseResult.okResult(apCommentList);
        }
        //用户登录,需要加载当前用户对评论点赞的列表
        List<ApCommentVo> apCommentVoList = new ArrayList<>();
        //获取当前文章所对应的评论id列表
        List<String> idlist = apCommentList.stream().map(apComment -> apComment.getId())
                .collect(Collectors.toList());
        // 查询 点赞批量列表 按照评论id 筛选
        Query query1 = Query.query(Criteria.where("commentId").in(idlist)
                .and("authorId").is(user.getId()));
        List<ApCommentLike> apCommentLikes = mongoTemplate.find(query1, ApCommentLike.class);
        // 遍历当前用户点赞列表 和当前评论列表
        if(CollectionUtils.isNotEmpty(apCommentList)
                && CollectionUtils.isNotEmpty(apCommentLikes)){
            apCommentList.forEach(comment ->{ //遍历所有文章列表ID
                ApCommentVo apCommentVo = new ApCommentVo();
                BeanUtils.copyProperties(comment, apCommentVo);
                //遍历当前用户点赞列表
                apCommentLikes.forEach(apCommentLike ->{
                    // 文章评论列表id 和 当前用户点赞评论列表id是否相等
                    if (comment.getId().equals(apCommentLike.getCommentId())) {
                        apCommentVo.setOperation((short) 0);
                    }
                });
                apCommentVoList.add(apCommentVo);
            });
            return ResponseResult.okResult(apCommentVoList);
        }
        return ResponseResult.okResult(apCommentList);
    }
    /**
     * 构建查询条件
     */
    private Query getQuery(CommentDTO dto) {
        return Query.query(Criteria.where("articleId").is(dto.getArticleId())
                .and("flag").is(0).and("createdTime").lt(dto.getMinDate()))
                .limit(dto.getSize()).with(Sort.by(Sort.Direction.DESC, "createdTime"));
    }
}
